home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / gfx / edit / TSMrph23s.lha / TSM23s.lha / Subroutines.c < prev    next >
C/C++ Source or Header  |  1993-10-08  |  59KB  |  2,335 lines

  1. // TSMorph - Amiga Morphing program
  2. // Copyright (C) © 1993  Topicsave Limited
  3.  
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // any later version.
  8.  
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13.  
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. // mpaddock@cix.compulink.co.uk
  19.  
  20. //    $Author: M_J_Paddock $
  21. //    $Date: 1993/09/04 17:43:32 $
  22. //    $Revision: 1.15 $
  23.  
  24. // include precompiled headers if required
  25. #ifndef TSMORPH_H
  26. #include "TSMorph.h"
  27. #endif
  28.  
  29. extern char TempFilename[256]="";    // file name buffer set up and used in various places
  30.  
  31. UBYTE r[256],g[256],b[256];            // Saved rgb colors
  32.  
  33. /* display short help message
  34.  * at top of window
  35.  * helpnum : number of help node
  36.  */
  37. void
  38. ihelp(ULONG helpnum) {
  39.     // only display if not zero, and there is a short message and the window is open
  40.     if (helpnum) {
  41.         if (*(ShortHelp[helpnum])) {
  42.             if (TSMorphWnd) {
  43.                 GT_SetGadgetAttrs(TSMorphGadgets[GDX_Help],TSMorphWnd,NULL,
  44.                                     GTTX_Text,ShortHelp[helpnum], TAG_END );
  45.             }
  46.         }
  47.     }
  48. }
  49.  
  50. /* Display help using amigaguide (if available)
  51.  * based on a number. Also displays short help message
  52.  */
  53. void
  54. help(ULONG helpnum) {
  55.     // display amigaguide if available
  56.     if (handle) {
  57.         SetAmigaGuideContext(handle,helpnum,NULL);
  58.         SendAmigaGuideContext(handle,NULL);
  59.     }
  60.     // display short message
  61.     ihelp(helpnum);
  62. }
  63.  
  64. /* Colour the picture based on it colormap
  65.  * Saving the palette for later use
  66.  * The palette is only set when the window is active and a menu is not displayed
  67.  */
  68. void
  69. ColorWindow(struct Picture *pic) {
  70.     UWORD i;                    // Loop counter
  71.     UWORD color;            // Colour
  72.     if (palette) {
  73.         if (pic) {
  74.             if (pic->ilbm->colortable) {
  75.                 // Store and set up to 256 colours
  76.                 for (i=0; i<min((1 << pic->Win->WScreen->BitMap.Depth),256); i++) {
  77.                     color = GetRGB4(pic->Win->WScreen->ViewPort.ColorMap,i);
  78.                     r[i]=(color&0x0f00)>>8;
  79.                     g[i]=(color&0x00f0)>>4;
  80.                     b[i]=(color&0x000f);
  81.                 }
  82.                 LoadRGB4(&(pic->Win->WScreen->ViewPort),pic->ilbm->colortable,
  83.                     MIN(pic->ilbm->ncolors,pic->Win->WScreen->ViewPort.ColorMap->Count));
  84.             }
  85.         }
  86.     }
  87. }
  88.  
  89. /* Reset the palette to the original
  90.  * stored in ColorWindow()
  91.  * Called when window becomes inactive or menu is to be displayed
  92.  *
  93.  * Note: This routine and the one above are not really allowed by CBM
  94.  *       But if no other program is changing the palette whilst its
  95.  *       window is inactive then everything should (amy) be OK.
  96.  */
  97. void
  98. UnColorWindow(struct Picture *pic) {
  99.     UWORD i;        // Loop counter
  100.     if (palette) {
  101.         if (pic) {
  102.             if (pic->ilbm->colortable) {
  103.                 for (i=0; i<min((1 << pic->Win->WScreen->BitMap.Depth),256); i++) {
  104.                     SetRGB4(&(pic->Win->WScreen->ViewPort),i,r[i],g[i],b[i]);
  105.                 }
  106.             }
  107.         }
  108.     }
  109. }
  110.  
  111. /* Standard CloseWindowSafely
  112.  * removing messages on shared ports
  113.  */
  114. void
  115. CloseWindowSafely(struct Window *win) {
  116.     Forbid();
  117.     StripIntuiMessages(win->UserPort,win);
  118.     win->UserPort = NULL;
  119.     ModifyIDCMP(win,0);
  120.     Permit();
  121.     CloseWindow(win);
  122. }
  123.  
  124. /* Standard StripIntuiMessages    */
  125. void
  126. StripIntuiMessages(struct MsgPort *mp,struct Window *win) {
  127.     struct IntuiMessage *msg, *succ;
  128.     msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
  129.     while(succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
  130.         if(msg->IDCMPWindow == win) {
  131.             Remove((struct Node *)msg);
  132.             ReplyMsg((struct Message *)msg);
  133.         }
  134.         msg = succ;
  135.     }
  136. }
  137.  
  138. /* Display an error message
  139.  * ErrorMessage    : The main text
  140.  * Gadget            : Text for one gadget
  141.  * extra                : more of the text
  142.  * helpnum            : Number of a help node
  143.  *
  144.  * Uses reqtools.library if available
  145.  */
  146. void
  147. Error(char *ErrorMessage,char *Gadget,char *extra,ULONG helpnum) {
  148.     struct EasyStruct EasyStruct = {
  149.         sizeof(struct EasyStruct),
  150.         0,
  151.         NULL,
  152.         NULL,
  153.         NULL
  154.     };
  155.     UBYTE *title = "TSMorph Error";
  156.     struct Window *req;
  157.     UBYTE gad[32] = "Help|";
  158.     UBYTE gad1[32] = "_Help|_";
  159.     ULONG ret = CALL_HANDLER;
  160.     struct AmigaGuideMsg *agm;
  161.     ULONG signals;
  162.     struct rtHandlerInfo *rth;
  163.     // Disable the windows and display the requester
  164.     DisableWindows(helpnum);
  165.     if (ReqToolsBase) {
  166.         // Set up gadgets depending on if amigaguide is available
  167.         if (!handle) {
  168.             strcpy(gad1,"_");
  169.         }
  170.         strcat(gad1,Gadget);
  171.         // This loops until OK is pressed, displaying help if Help is pressed (if present)
  172.         while (ret) {
  173.             ret = CALL_HANDLER;
  174.             if (rtEZRequestTags(ErrorMessage,gad1,NULL,&extra,
  175.                                         RT_ReqHandler,    &rth,
  176.                                         RT_Window,        TSMorphWnd,
  177.                                         RT_Underscore,    '_',
  178.                                         RTEZ_ReqTitle,    title,
  179.                                         TAG_END) == CALL_HANDLER) {
  180.                 while (ret == CALL_HANDLER) {
  181.                     if (!rth->DoNotWait) {
  182.                         signals = Wait(rth->WaitMask | ASig);
  183.                     }
  184.                     ret = rtReqHandlerA(rth,signals,NULL);
  185.                     if (ret == 1) {
  186.                         help(helpnum);
  187.                     }
  188.                     if (signals & ASig) {
  189.                           while (agm = GetAmigaGuideMsg(handle)) {
  190.                              ReplyAmigaGuideMsg(agm);
  191.                          }
  192.                      }
  193.                 }
  194.             }
  195.             else {
  196.                 ret = 0;
  197.             }
  198.         }
  199.     }
  200.     else {
  201.         EasyStruct.es_TextFormat = ErrorMessage;
  202.         EasyStruct.es_Title = title;
  203.         // Set up gadgets depending on if amigaguide is available
  204.         if (handle) {
  205.             strcat(gad,Gadget);
  206.         }
  207.         else {
  208.             strcpy(gad,Gadget);
  209.         }
  210.         EasyStruct.es_GadgetFormat = gad;
  211.         req = BuildEasyRequest(TSMorphWnd,&EasyStruct,NULL,extra);
  212.         // This loops until OK is pressed, displaying help if Help is pressed (if present)
  213.         while (ret) {
  214.             signals  = Wait((1L << req->UserPort->mp_SigBit) | ASig);
  215.             if (signals & (1L << req->UserPort->mp_SigBit)) {
  216.                 ret = SysReqHandler(req,NULL,FALSE);
  217.                 if (ret == 1) {
  218.                     help(helpnum);
  219.                 }
  220.             }
  221.             if (signals & ASig) {
  222.                   while (agm = GetAmigaGuideMsg(handle)) {
  223.                      ReplyAmigaGuideMsg(agm);
  224.                  }
  225.             }
  226.         }
  227.         FreeSysRequest(req);
  228.     }
  229.     EnableWindows();
  230. }
  231.  
  232. /* As Error but
  233.  * pic    : a picture to uncolor if required
  234.  */
  235. void
  236. XError(struct Picture *pic,char *ErrorMessage,char *Gadget,char *extra,ULONG helpnum) {
  237.     UnColorWindow(pic);
  238.     Error(ErrorMessage,Gadget,extra,helpnum);
  239.     ColorWindow(pic);
  240. }
  241.  
  242. /* Draw all points
  243.  * in both windows
  244.  */
  245. void
  246. DrawAllPoints(void) {
  247.     struct MyPoint *MyPoint;
  248.     // For each point
  249.     for (MyPoint = (struct MyPoint *)PointList.lh_Head;
  250.                           MyPoint->MyNode.mln_Succ;
  251.                           MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
  252.         // Draw point in image 1
  253.         DrawPixels(&Pic1,MyPoint->x,MyPoint->y,NULL);
  254.         /* For each linked point draw a line
  255.          * to the other if the other is a "later" point
  256.          */
  257.         if (MyPoint->p1 > MyPoint) {
  258.             MyDraw(Pic1.Win->RPort,MyPoint->p1->x<<Zoom,MyPoint->p1->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  259.         }    
  260.         if (MyPoint->p2 > MyPoint) {
  261.             MyDraw(Pic1.Win->RPort,MyPoint->p2->x<<Zoom,MyPoint->p2->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  262.         }
  263.         if (MyPoint->p3 > MyPoint) {
  264.             MyDraw(Pic1.Win->RPort,MyPoint->p3->x<<Zoom,MyPoint->p3->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  265.         }
  266.         if (MyPoint->p4 > MyPoint) {
  267.             MyDraw(Pic1.Win->RPort,MyPoint->p4->x<<Zoom,MyPoint->p4->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  268.         }
  269.         // Same stuff for image 2
  270.         DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,NULL);
  271.         if (MyPoint->p1 > MyPoint) {
  272.             MyDraw(Pic2.Win->RPort,MyPoint->p1->x1<<Zoom,MyPoint->p1->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  273.         }    
  274.         if (MyPoint->p2 > MyPoint) {
  275.             MyDraw(Pic2.Win->RPort,MyPoint->p2->x1<<Zoom,MyPoint->p2->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  276.         }
  277.         if (MyPoint->p3 > MyPoint) {
  278.             MyDraw(Pic2.Win->RPort,MyPoint->p3->x1<<Zoom,MyPoint->p3->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  279.         }
  280.         if (MyPoint->p4 > MyPoint) {
  281.             MyDraw(Pic2.Win->RPort,MyPoint->p4->x1<<Zoom,MyPoint->p4->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  282.         }
  283.     }
  284. }
  285.  
  286. /* Handle Raw Key in Information
  287.  * Window - from GadToolsBox
  288.  */
  289. int
  290. TSMorphRawKey(void) {
  291.     UWORD X,Y;        // Mouse position
  292.     ULONG HNum;        // Help node
  293.     X = TSMorphWnd->MouseX;
  294.     Y = TSMorphWnd->MouseY;
  295.     switch (TSMorphMsg.Code) {
  296.     // only help key does anything
  297.     case 0x5f:
  298.         /* Find gadget pointer is in
  299.          * otherwise use whole window
  300.          */
  301.         if (PointInBox(X,Y,Rect[GDX_Help].MinX,Rect[GDX_Help].MinY,
  302.                                 Rect[GDX_Help].MaxX,Rect[GDX_Help].MaxY))
  303.             HNum = H_HelpGad;
  304.         else
  305.         if (PointInBox(X,Y,Rect[GDX_GetFile1].MinX,Rect[GDX_GetFile1].MinY,
  306.                                 Rect[GDX_GetFile1].MaxX,Rect[GDX_GetFile1].MaxY))
  307.             HNum = H_G24File1;
  308.         else
  309.         if (PointInBox(X,Y,Rect[GDX_GetFile2].MinX,Rect[GDX_GetFile2].MinY,
  310.                                 Rect[GDX_GetFile2].MaxX,Rect[GDX_GetFile2].MaxY))
  311.             HNum = H_G24File2;
  312.         else
  313.         if (PointInBox(X,Y,Rect[GDX_Width].MinX,Rect[GDX_Width].MinY,
  314.                                 Rect[GDX_Width].MaxX,Rect[GDX_Width].MaxY))
  315.             HNum = H_Width;
  316.         else
  317.         if (PointInBox(X,Y,Rect[GDX_Height].MinX,Rect[GDX_Height].MinY,
  318.                                 Rect[GDX_Height].MaxX,Rect[GDX_Height].MaxY))
  319.             HNum = H_Height;
  320.         else
  321.         if (PointInBox(X,Y,Rect[GDX_GetFileOne].MinX,Rect[GDX_GetFileOne].MinY,
  322.                                 Rect[GDX_GetFileOne].MaxX,Rect[GDX_GetFileOne].MaxY))
  323.             HNum = H_GFileOne;
  324.         else
  325.         if (PointInBox(X,Y,Rect[GDX_GetFileTwo].MinX,Rect[GDX_GetFileTwo].MinY,
  326.                                 Rect[GDX_GetFileTwo].MaxX,Rect[GDX_GetFileTwo].MaxY))
  327.             HNum = H_GFileTwo;
  328.         else
  329.         if (PointInBox(X,Y,Rect[GDX_EditPoints].MinX,Rect[GDX_EditPoints].MinY,
  330.                                 Rect[GDX_EditPoints].MaxX,Rect[GDX_EditPoints].MaxY))
  331.             HNum = H_EPoints;
  332.         else
  333.         if (PointInBox(X,Y,Rect[GDX_SinglePicture].MinX,Rect[GDX_SinglePicture].MinY,
  334.                                 Rect[GDX_SinglePicture].MaxX,Rect[GDX_SinglePicture].MaxY))
  335.             HNum = H_Single;
  336.         else
  337.         if (PointInBox(X,Y,Rect[GDX_GetSaveName].MinX,Rect[GDX_GetSaveName].MinY,
  338.                                 Rect[GDX_GetSaveName].MaxX,Rect[GDX_GetSaveName].MaxY))
  339.             HNum = H_GName;
  340.         else
  341.         if (PointInBox(X,Y,Rect[GDX_FileOne].MinX,Rect[GDX_FileOne].MinY,
  342.                                 Rect[GDX_FileOne].MaxX,Rect[GDX_FileOne].MaxY))
  343.             HNum = H_FileOne;
  344.         else
  345.         if (PointInBox(X,Y,Rect[GDX_FileTwo].MinX,Rect[GDX_FileTwo].MinY,
  346.                                 Rect[GDX_FileTwo].MaxX,Rect[GDX_FileTwo].MaxY))
  347.             HNum = H_FileTwo;
  348.         else
  349.         if (PointInBox(X,Y,Rect[GDX_File241].MinX,Rect[GDX_File241].MinY,
  350.                                 Rect[GDX_File241].MaxX,Rect[GDX_File241].MaxY))
  351.             HNum = H_24File1;
  352.         else
  353.         if (PointInBox(X,Y,Rect[GDX_File242].MinX,Rect[GDX_File242].MinY,
  354.                                 Rect[GDX_File242].MaxX,Rect[GDX_File242].MaxY))
  355.             HNum = H_24File2;
  356.         else
  357.         if (PointInBox(X,Y,Rect[GDX_Frames].MinX,Rect[GDX_Frames].MinY,
  358.                                 Rect[GDX_Frames].MaxX,Rect[GDX_Frames].MaxY))
  359.             HNum = H_Frames;
  360.         else
  361.         if (PointInBox(X,Y,Rect[GDX_Start].MinX,Rect[GDX_Start].MinY,
  362.                                 Rect[GDX_Start].MaxX,Rect[GDX_Start].MaxY))
  363.             HNum = H_Start;
  364.         else
  365.         if (PointInBox(X,Y,Rect[GDX_Name].MinX,Rect[GDX_Name].MinY,
  366.                                 Rect[GDX_Name].MaxX,Rect[GDX_Name].MaxY))
  367.             HNum = H_Name;
  368.         else
  369.         // following should use the gadget sizing stuff - doubt if anybody will notice
  370.         if (PointInBox(X,Y,0,0,
  371.                                 20,TSMorphWnd->BorderTop))
  372.             HNum = H_IClose;
  373.         else
  374.         if (PointInBox(X,Y,(TSMorphWnd->Width - 24),0,
  375.                                 TSMorphWnd->Width,TSMorphWnd->BorderTop))
  376.             HNum = H_IDepth;
  377.         else
  378.         if (PointInBox(X,Y,(TSMorphWnd->Width - 24 - 24),0,
  379.                                 (TSMorphWnd->Width - 24),TSMorphWnd->BorderTop))
  380.             HNum = H_IZoom;
  381.         else
  382.             HNum = H_IWindow;
  383.         help(HNum);
  384.         break;
  385.     }
  386.     return 1;
  387. }
  388.  
  389. /* Handle Vanilla Key in Information
  390.  * Window - from GadToolsBox
  391.  */
  392. int
  393. TSMorphVanillaKey(void) {
  394.     switch (TSMorphMsg.Code) {
  395.     case 'o':
  396.     case 'O':
  397.         /* O - if control window not open
  398.          * either activate string gadget
  399.          * or display file requester with shift
  400.          */
  401.         if (!ControlWindow) {
  402.             if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  403.                 GetFileOneClicked();
  404.             }
  405.             else {
  406.                 ActivateGadget(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL);
  407.             }
  408.         }
  409.         break;
  410.     case 't':
  411.     case 'T':
  412.         /* T - if control window not open
  413.          * either activate string gadget
  414.          * or display file requester with shift
  415.          */
  416.         if (!ControlWindow) {
  417.             if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  418.                 GetFileTwoClicked();
  419.             }
  420.             else {
  421.                 ActivateGadget(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL);
  422.             }
  423.         }
  424.         break;
  425.     case '1':
  426.     case '!':
  427.         /* 1 - either activate string gadget
  428.          * or display file requester with shift
  429.          */
  430.         if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  431.             GetFile1Clicked();
  432.         }
  433.         else {
  434.             ActivateGadget(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL);
  435.         }
  436.         break;
  437.     case '2':
  438.     case '"':
  439.         /* 2 - either activate string gadget
  440.          * or display file requester with shift
  441.          */
  442.         if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  443.             GetFile2Clicked();
  444.         }
  445.         else {
  446.             ActivateGadget(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL);
  447.         }
  448.         break;
  449.     case 'r':
  450.     case 'R':
  451.         // R - Cycle Single
  452.         if (!ControlWindow) {
  453.             if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  454.                 if (!SinglePicture) {
  455.                     // If we do not have reqtools then do not allow Anims
  456.                     if (ReqToolsBase) {
  457.                         SinglePicture = 3;
  458.                     }
  459.                     else {
  460.                         SinglePicture = 1;
  461.                     }
  462.                 }
  463.                 else {
  464.                     --SinglePicture;
  465.                 }
  466.             }
  467.             else {
  468.                 if (ReqToolsBase) {
  469.                     // If we do not have reqtools then do not allow Anims
  470.                     if (SinglePicture == 3) {
  471.                         SinglePicture = 0;
  472.                     }
  473.                     else {
  474.                         ++SinglePicture;
  475.                     }
  476.                 }
  477.                 else {
  478.                     if (SinglePicture == 1) {
  479.                         SinglePicture = 0;
  480.                     }
  481.                     else {
  482.                         ++SinglePicture;
  483.                     }
  484.                 }
  485.             }
  486.             Saved = FALSE;
  487.             GT_SetGadgetAttrs(TSMorphGadgets[GDX_SinglePicture],TSMorphWnd,NULL,
  488.                                     GTCY_Active,SinglePicture, TAG_END );
  489.         }
  490.         break;
  491.     case 'f':
  492.     case 'F':
  493.         // F - activate string gadgtet
  494.         if (!ControlWindow) {
  495.             ActivateGadget(TSMorphGadgets[GDX_Frames],TSMorphWnd,NULL);
  496.         }
  497.         break;
  498.     case 'a':
  499.     case 'A':
  500.         // A - activate string gadgtet
  501.         if (!ControlWindow) {
  502.             ActivateGadget(TSMorphGadgets[GDX_Start],TSMorphWnd,NULL);
  503.         }
  504.         break;
  505.     case 'n':
  506.     case 'N':
  507.         /* N - either activate string gadget
  508.          * or display file requester with shift
  509.          */
  510.         if (TSMorphMsg.Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  511.             GetSaveNameClicked();
  512.         }
  513.         else {
  514.             ActivateGadget(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL);
  515.         }
  516.         break;
  517.     case 'p':
  518.     case 'P':
  519.         /* P - either open Control and image windows
  520.          * or activate and bring control window to front
  521.          */
  522.         if (!ControlWindow) {
  523.             OpenPointsEdit();
  524.         }
  525.         else {
  526.             ActivateWindow(ControlWindow);
  527.             WindowToFront(ControlWindow);
  528.         }
  529.         break;
  530.     default:
  531.         // other key
  532.         break;
  533.     }
  534.     return 1;
  535. }
  536.  
  537. /* Open... menu item in Info window */
  538. int
  539. TSMorphMenuOpen(void) {
  540.     // Just call MyOpen();
  541.     DisableWindows(DI_WaitOpen);
  542.     MyOpen(NULL,FALSE,TRUE);
  543.     EnableWindows();
  544.     return 1;
  545. }
  546.  
  547. /* Save menu item in Info window */
  548. int TSMorphMenuSave(void) {
  549.     // Just call SaveAs(last saved name)
  550.     DisableWindows(DI_WaitSave);
  551.     SaveAs(savedfilename);
  552.     EnableWindows();
  553.       return 1;
  554. }
  555.  
  556. /* Save As... menu item in Info window */
  557. int
  558. TSMorphMenuSaveAs(void) {
  559.     // Just call SaveAs(no name)
  560.     DisableWindows(DI_WaitSave);
  561.     SaveAs(NULL);
  562.     EnableWindows();
  563.     return 1;
  564. }
  565.  
  566. /* Delete... menu item in Info window */
  567. int
  568. TSMorphMenuDelete(void) {
  569.     BPTR cd;
  570.     BOOL ok = TRUE;
  571.     struct AnchorPath ap = {0};
  572.     // Delete a project with Icon and all .nnn files
  573.     DisableWindows(DI_Delete);
  574.     if (GetAFile("","TSMorph - Delete Project",FILF_SAVE)) {
  575.         // delete main file and icon
  576.         DeleteFile(TempFilename);
  577.         DeleteDiskObject(TempFilename);
  578.         // delete "project.nnn" files
  579.         strcat(TempFilename,".[0-9][0-9][0-9]");
  580.         if (!MatchFirst(TempFilename,&ap)) {
  581.             while (ok) {
  582.                 cd = CurrentDir(ap.ap_Current->an_Lock);
  583.                 DeleteFile(ap.ap_Info.fib_FileName);
  584.                 CurrentDir(cd);
  585.                 ok = !MatchNext(&ap);
  586.             }
  587.         }
  588.         MatchEnd(&ap);
  589.     }
  590.     EnableWindows();
  591.     return 1;
  592. }
  593.  
  594. /* About menu item in Info window */
  595. int
  596. TSMorphMenuAbout(void) {
  597.     // Just Call About()
  598.     DisableWindows(DI_About);
  599.     About();
  600.     EnableWindows();
  601.     return 1;
  602. }
  603.  
  604. /* Quit menu item in Info window */
  605. int
  606. TSMorphMenuQuit(void) {
  607.     // Suggest save - quit if requested
  608.       if (!Saved) {
  609.          return !SaveRequester();
  610.       }
  611.       else {
  612.           return 0;
  613.       }
  614. }
  615.  
  616. /* Edit Points... menu item in Info window */
  617. int
  618. TSMorphMenuEditPoints(void) {
  619.     // Open window if not open
  620.     if (!ControlWindow) {
  621.         OpenPointsEdit();
  622.     }
  623.     // Otherwise activate and bring to front
  624.     else {
  625.         ActivateWindow(ControlWindow);
  626.         WindowToFront(ControlWindow);
  627.     }
  628.     return 1;
  629. }
  630.  
  631. /* Window closed, acts like quit    */
  632. int TSMorphCloseWindow(void) {
  633.     // Suggest save - quit if required
  634.       if (!Saved) {
  635.          return !SaveRequester();
  636.       }
  637.       else {
  638.           return 0;
  639.       }
  640. }
  641.  
  642. /* Help pressed on a menu in the info window    */
  643. int
  644. TSMorphMenuHelp(void) {
  645.     ULONG HNum;        // Help node
  646.     // Forget any previous changes
  647.     // This means all menu selections before help is pressed are ignored
  648.     RemoveMenus();
  649.     SwitchMenuItem(MM_PALETTE,palette,FALSE);
  650.     SwitchMenuItem(MM_ZOOM,Zoom,FALSE);
  651.     SwitchMenuItem(MM_ICONSP,CreateIconsP,FALSE);
  652.     UpdateOpenMode(FALSE);
  653.     SwitchMenuItem(MM_ICONSR,CreateIconsR,FALSE);
  654.     UpdateRenderMode(FALSE);
  655.     UpdateSaveFormat(FALSE);
  656.     AddMenus();
  657.     // Determine help number from menu position
  658.     switch (TSMorphMsg.Code) {
  659.     case FULLMENUNUM(0,NOITEM,NOSUB):
  660.     case FULLMENUNUM(0,2,NOSUB):
  661.     case FULLMENUNUM(0,6,NOSUB):
  662.     case FULLMENUNUM(0,8,NOSUB):
  663.     case FULLMENUNUM(0,10,NOSUB):
  664.         HNum = H_IMP;
  665.         break;
  666.     case FULLMENUNUM(0,0,NOSUB):
  667.         HNum = H_IMPN;
  668.         break;
  669.     case FULLMENUNUM(0,1,NOSUB):
  670.         HNum = H_IMPO;
  671.         break;
  672.     case FULLMENUNUM(0,3,NOSUB):
  673.         HNum = H_IMPS;
  674.         break;
  675.     case FULLMENUNUM(0,4,NOSUB):
  676.         HNum = H_IMPSA;
  677.         break;
  678.     case FULLMENUNUM(0,5,NOSUB):
  679.         HNum = H_IMPD;
  680.         break;
  681.     case FULLMENUNUM(0,7,NOSUB):
  682.         HNum = H_IMPA;
  683.         break;
  684.     case FULLMENUNUM(0,9,NOSUB):
  685.         HNum = H_IMPQ;
  686.         break;
  687.     case FULLMENUNUM(0,11,NOSUB):
  688.         HNum = H_IMPP;
  689.         break;
  690.     case FULLMENUNUM(0,12,NOSUB):
  691.         HNum = H_IMPE;
  692.         break;
  693.     case FULLMENUNUM(1,NOITEM,NOSUB):
  694.     case FULLMENUNUM(1,MM_C1,NOSUB):
  695.     case FULLMENUNUM(1,MM_C2,NOSUB):
  696.     case FULLMENUNUM(1,MM_C3,NOSUB):
  697.     case FULLMENUNUM(1,MM_C4,NOSUB):
  698.         HNum = H_IMS;
  699.         break;
  700.     case FULLMENUNUM(1,MM_ICONS,NOSUB):
  701.         HNum = H_P_CI;
  702.         break;
  703.     case FULLMENUNUM(1,MM_PALETTE,NOSUB):
  704.         HNum = H_P_CP;
  705.         break;
  706.     case FULLMENUNUM(1,MM_ZOOM,NOSUB):
  707.         HNum = H_P_ZO;
  708.         break;
  709.     case FULLMENUNUM(1,MM_OPENMODE,NOSUB):
  710.     case FULLMENUNUM(1,MM_OPENMODE,MI_ALWAYS):
  711.     case FULLMENUNUM(1,MM_OPENMODE,MI_IFILBM):
  712.     case FULLMENUNUM(1,MM_OPENMODE,MI_IFCOLOURS):
  713.     case FULLMENUNUM(1,MM_OPENMODE,MI_REMAP):
  714.     case FULLMENUNUM(1,MM_OPENMODE,MI_OPAL):
  715.         HNum = H_P_OM;
  716.         break;
  717.     case FULLMENUNUM(1,MM_SCREEN,NOSUB):
  718.         HNum = H_P_PS;
  719.         break;
  720.     case FULLMENUNUM(1,MM_CUSTOM,NOSUB):
  721.         HNum = H_PCUSTM;
  722.         break;
  723.     case FULLMENUNUM(1,MM_CDEPTH,NOSUB):
  724.         HNum = H_PCUSTD;
  725.         break;
  726.     case FULLMENUNUM(1,MM_SPREVIEW,NOSUB):
  727.         HNum = H_P_Preview;
  728.         break;
  729.     case FULLMENUNUM(1,MM_ICONSP,NOSUB):
  730.         HNum = H_P_CIP;
  731.         break;
  732.     case FULLMENUNUM(1,MM_KEEPS,NOSUB):
  733.         HNum = H_P_KS;
  734.         break;
  735.     case FULLMENUNUM(1,MM_LOADS,NOSUB):
  736.         HNum = H_P_LOADS;
  737.         break;
  738.     case FULLMENUNUM(1,MM_SAVES,NOSUB):
  739.         HNum = H_P_SAVES;
  740.         break;
  741.     case FULLMENUNUM(1,MM_SAVESAS,NOSUB):
  742.         HNum = H_P_SAVESAS;
  743.         break;
  744.     case FULLMENUNUM(1,MM_ICONSR,NOSUB):
  745.         HNum = H_P_CIR;
  746.         break;
  747.     case FULLMENUNUM(1,MM_DX,NOSUB):
  748.         HNum = H_P_DX;
  749.         break;
  750.     case FULLMENUNUM(1,MM_DY,NOSUB):
  751.         HNum = H_P_DY;
  752.         break;
  753.     case FULLMENUNUM(1,MM_LOADSCRIPT,NOSUB):
  754.         HNum = H_P_LS;
  755.         break;
  756.     case FULLMENUNUM(1,MM_PRESCRIPT,NOSUB):
  757.         HNum = H_P_PES;
  758.         break;
  759.     case FULLMENUNUM(1,MM_POSTSCRIPT,NOSUB):
  760.         HNum = H_P_POS;
  761.         break;
  762.     case FULLMENUNUM(1,MM_DEPTH,NOSUB):
  763.         HNum = H_P_DE;
  764.         break;
  765.     case FULLMENUNUM(1,MM_RENDERMODE,NOSUB):
  766.     case FULLMENUNUM(1,MM_RENDERMODE,MI_MODE0):
  767.     case FULLMENUNUM(1,MM_RENDERMODE,MI_MODE1):
  768.     case FULLMENUNUM(1,MM_RENDERMODE,MI_MODE2):
  769.     case FULLMENUNUM(1,MM_RENDERMODE,MI_MODE3):
  770.         HNum = H_P_MO;
  771.         break;
  772.     case FULLMENUNUM(1,MM_SAVEFORMAT,NOSUB):
  773.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_ILBM24):
  774.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_OPAL24):
  775.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_OPAL24T):
  776.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_OPAL24F):
  777.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_OPAL24FT):
  778.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_JPEG):
  779.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_JPEGT):
  780.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_PBM):
  781.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_BW16):
  782.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_BW256):
  783.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_HAM6):
  784.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_HAM8):
  785.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_DCTV3):
  786.     case FULLMENUNUM(1,MM_SAVEFORMAT,MI_DCTV4):
  787.         HNum = H_P_SF;
  788.         break;
  789.     case FULLMENUNUM(1,MM_QUALITY,NOSUB):
  790.         HNum = H_P_QU;
  791.         break;
  792.     case FULLMENUNUM(1,MM_SCREENR,NOSUB):
  793.         HNum = H_P_PSR;
  794.         break;
  795.     case FULLMENUNUM(1,MM_ANTIALIAS,NOSUB):
  796.         HNum = H_P_AA;
  797.         break;
  798.     case FULLMENUNUM(1,MM_RESETD,NOSUB):
  799.         HNum = H_S_RD;
  800.         break;
  801.     case FULLMENUNUM(1,MM_LASTS,NOSUB):
  802.         HNum = H_S_LS;
  803.         break;
  804.     case FULLMENUNUM(1,MM_RESTORE,NOSUB):
  805.         HNum = H_S_R;
  806.         break;
  807.     case FULLMENUNUM(1,MM_HELP,NOSUB):
  808.         HNum = H_P_HE;
  809.         break;
  810.     case MENUNULL:
  811.     default:
  812.         HNum = H_IM;
  813.         break;
  814.     }
  815.     // Display help
  816.     help(HNum);
  817.     return 1;
  818. }
  819.  
  820. /* String gadget clicked */
  821. int
  822. File241Clicked(void) {
  823.     // Only read when required    - display help if help pressed
  824.     if (TSMorphMsg.Code == 0x5F) {
  825.         help(H_24File1);
  826.     }
  827.     Saved = FALSE;
  828.     return 1;
  829. }
  830.  
  831. /* String gadget clicked */
  832. int
  833. File242Clicked(void) {
  834.     // Only read when required    - display help if help pressed
  835.     if (TSMorphMsg.Code == 0x5F) {
  836.         help(H_24File2);
  837.     }
  838.     Saved = FALSE;
  839.     return 1;
  840. }
  841.  
  842. /* String gadget clicked */
  843. int
  844. FramesClicked(void) {
  845.     // Only read when required    - display help if help pressed
  846.     if (TSMorphMsg.Code == 0x5F) {
  847.         help(H_Frames);
  848.     }
  849.     Saved = FALSE;
  850.     return 1;
  851. }
  852.  
  853. /* String gadget clicked */
  854. int
  855. FileOneClicked(void) {
  856.     // Only read when required    - display help if help pressed
  857.     if (TSMorphMsg.Code == 0x5F) {
  858.         help(H_FileOne);
  859.     }
  860.     Saved = FALSE;
  861.     return 1;
  862. }
  863.  
  864. /* String gadget clicked */
  865. int FileTwoClicked(void) {
  866.     // Only read when required    - display help if help pressed
  867.     if (TSMorphMsg.Code == 0x5F) {
  868.         help(H_FileTwo);
  869.     }
  870.     Saved = FALSE;
  871.     return 1;
  872. }
  873.  
  874. /* CheckBox clicked */
  875. int
  876. SinglePictureClicked(void) {
  877.     // Toggle BOOL
  878.     SinglePicture = TSMorphMsg.Code;
  879.     Saved = FALSE;
  880.     return 1;
  881. }
  882.  
  883. /* String gadget clicked */
  884. int
  885. NameClicked(void) {
  886.     // Only read when required    - display help if help pressed
  887.     if (TSMorphMsg.Code == 0x5F) {
  888.         help(H_Name);
  889.     }
  890.     Saved = FALSE;
  891.     return 1;
  892. }
  893.  
  894. /* String gadget clicked */
  895. int
  896. StartClicked(void) {
  897.     // Read when required - display help if help pressed
  898.     if (TSMorphMsg.Code == 0x5F) {
  899.         help(H_Start);
  900.     }
  901.     Saved = FALSE;
  902.     return 1;
  903. }
  904.  
  905. /* Edit Points gadget clicked */
  906. int
  907. EditPointsClicked(void) {
  908.     // Open window if not open
  909.     if (!ControlWindow) {
  910.         OpenPointsEdit();
  911.     }
  912.     // Otherwise activate and bring to front
  913.     else {
  914.         ActivateWindow(ControlWindow);
  915.         WindowToFront(ControlWindow);
  916.     }
  917.     return 1;
  918. }
  919.  
  920. /* Open the Control and Image Windows    */
  921. void
  922. OpenPointsEdit(void) {
  923.     char buffer[257];
  924.     BOOL ok=TRUE;
  925.     // Open Control window, Pic1 and Pic2
  926.     if ((SinglePicture == 2) || (SinglePicture == 3)) {    // Anim so need frame number
  927.         ok = GetFrameNumber();
  928.     }
  929.     if (ok) {
  930.         if (ControlWindow = OpenControlWindow()) {            // note multiple calls to DisableWindows()
  931.             DisableWindows(DI_Image1);                                // are safe, required to disable just opened window
  932.             Pic1_Open = openAPicture(GetString(TSMorphGadgets[GDX_FileOne]),&Pic1,TRUE);
  933.             if (Pic1_Open) {
  934.                 DisableWindows(DI_Image2);
  935.                   Pic2_Open = openAPicture(GetString(TSMorphGadgets[GDX_FileTwo]),&Pic2,TRUE);
  936.                 if (Pic2_Open) {
  937.                      DisableWindows(DI_Draw);
  938.                      // validate image sizes
  939.                        if ((Pic1.ilbm->Bmhd.w != Pic2.ilbm->Bmhd.w) ||
  940.                             (Pic1.ilbm->Bmhd.h != Pic2.ilbm->Bmhd.h)) {
  941.                            Error("Both Images must be the same size","OK",NULL,HE_Size);
  942.                         CloseAPicture(&Pic2);
  943.                           Pic2_Open = FALSE;
  944.                         CloseAPicture(&Pic1);
  945.                           Pic1_Open = FALSE;
  946.                         }
  947.                         else {
  948.                             // if we have changed from non anim to anim then we may still have
  949.                             // points in memory - so draw, otherwise try and load points file
  950.                         if ((!(((struct MyPoint *)PointList.lh_Head)->MyNode.mln_Succ)) &&
  951.                             ((SinglePicture == 2) || (SinglePicture == 3))) {
  952.                             strcpy(TempFilename,savedfilename);
  953.                             strcat(TempFilename,".%03ld");
  954.                             sprintf(buffer,TempFilename,FrameNumber);
  955.                             MyOpen(buffer,TRUE,FALSE);
  956.                         }
  957.                         else {
  958.                             DrawAllPoints();
  959.                         }
  960.                             // disable some menus, generally set up and activate things
  961.                         SetMyPointer();
  962.                         EnableWindows();
  963.                         OffMenu(TSMorphWnd,FULLMENUNUM(0,0,NOSUB));
  964.                         OffMenu(TSMorphWnd,FULLMENUNUM(0,1,NOSUB));
  965.                         ActivateWindow(ControlWindow);
  966.                         return;
  967.                     }
  968.                 }
  969.                 // Tidy up and close down cleanly
  970.                 else {
  971.                     CloseAPicture(&Pic1);
  972.                       Pic1_Open = FALSE;
  973.                 }
  974.             }
  975.             CloseControlWindow();
  976.         }
  977.         EnableWindows();
  978.     }
  979. }
  980.  
  981. /* Display ASL requesters    */
  982. int
  983. GetFile1Clicked(void) {
  984.     if (GetAFile(GetString(TSMorphGadgets[GDX_File241]),"TSMorph - 24 bit pic 1",0)) {
  985.         GT_SetGadgetAttrs(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL,
  986.                                 GTST_String, TempFilename, TAG_END );
  987.         Saved = FALSE;
  988.     }
  989.     return 1;
  990. }
  991.  
  992. /* Display ASL requesters    */
  993. int
  994. GetFile2Clicked(void) {
  995.     if (GetAFile(GetString(TSMorphGadgets[GDX_File242]),"TSMorph - 24 bit pic 2",0)) {
  996.         GT_SetGadgetAttrs(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL,
  997.                                 GTST_String, TempFilename, TAG_END );
  998.         Saved = FALSE;
  999.     }
  1000.     return 1;
  1001. }
  1002.  
  1003. /* Display ASL requesters    */
  1004. int
  1005. GetFileOneClicked(void) {
  1006.     if (!ControlWindow) {
  1007.         if (GetAFile(GetString(TSMorphGadgets[GDX_FileOne]),"TSMorph - pic 1",0)) {
  1008.             GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL,
  1009.                                     GTST_String, TempFilename, TAG_END );
  1010.             Saved = FALSE;
  1011.         }
  1012.     }
  1013.     return 1;
  1014. }
  1015.  
  1016. /* Display ASL requesters    */
  1017. int
  1018. GetFileTwoClicked(void) {
  1019.     if (!ControlWindow) {
  1020.         if (GetAFile(GetString(TSMorphGadgets[GDX_FileTwo]),"TSMorph - pic 2",0)) {
  1021.             GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL,
  1022.                                     GTST_String, TempFilename, TAG_END );
  1023.             Saved = FALSE;
  1024.         }
  1025.     }
  1026.     return 1;
  1027. }
  1028.  
  1029. /* Display ASL requesters    */
  1030. int
  1031. GetSaveNameClicked(void) {
  1032.     if (GetAFile(GetString(TSMorphGadgets[GDX_Name]),"TSMorph - Morph file name",0)) {
  1033.         GT_SetGadgetAttrs(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL,
  1034.                                 GTST_String, TempFilename, TAG_END );
  1035.         Saved = FALSE;
  1036.     }
  1037.     return 1;
  1038. }
  1039.  
  1040. /* Displays requester to add a grid of points */
  1041. void
  1042. AddGrid(void) {
  1043.     int flag = 1;
  1044.     // Open window and wait till close selected then close it
  1045.     DisableWindows(DI_Grid);
  1046.     if (!OpenGridRequestWindow()) {
  1047.         while (flag) {
  1048.             Wait((1L << GridRequestWnd->UserPort->mp_SigBit));
  1049.             flag = HandleGridRequestIDCMP();
  1050.         }
  1051.     }
  1052.     else {
  1053.         Error("Unable to %s","OK","Open Grid Requester",HE_OGrid);
  1054.     }
  1055.     CloseGridRequestWindow();
  1056.     EnableWindows();
  1057. }
  1058.  
  1059. /* Actually add the grid of points    */
  1060. void
  1061. ReallyAddGrid(void) {
  1062.     UWORD xgrid;    //    Number horizontally
  1063.     UWORD ygrid;    // Number vertically
  1064.     UWORD x;            // X coord
  1065.     UWORD y;            // Y coord
  1066.     BOOL ok = TRUE;// Is it working?
  1067.     struct MyPoint **MyPointp;    // Point Pointer
  1068.     struct MyPoint *MyPoint;    // Point
  1069.     // Read X and Y numbers
  1070.     xgrid = GetNumber(GridRequestGadgets[GDX_XCells]);
  1071.     ygrid = GetNumber(GridRequestGadgets[GDX_YCells]);
  1072.     if (xgrid && ygrid) {
  1073.         /* Allocate Pointer to points memory
  1074.          * We need an array but cannot allocate all points
  1075.          * as one block of memory as a single point can be deleted
  1076.          */
  1077.         if (MyPointp = AllocMem(sizeof(struct MyPoint *)*((xgrid+1)*(ygrid+1)),MEMF_CLEAR)) {
  1078.             // Create and draw all points
  1079.             for (x = 0;
  1080.                     ok && (x <= xgrid);
  1081.                     ++x) {
  1082.                 for (y = 0;
  1083.                         ok  && (y <= ygrid);
  1084.                         ++y) {
  1085.                     if (MyPoint = MyPointp[x*(xgrid+1)+y] = AllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
  1086.                         Saved = FALSE;
  1087.                         MyPoint->x = (x * (Width-1))/xgrid;
  1088.                         MyPoint->y = (y * (Height-1))/ygrid;
  1089.                         MyPoint->x1 = MyPoint->x;
  1090.                         MyPoint->y1 = MyPoint->y;
  1091.                         AddTail(&PointList,(struct Node *)MyPoint);
  1092.                         DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
  1093.                         DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
  1094.                     }
  1095.                     else {
  1096.                         ok = FALSE;
  1097.                     }
  1098.                 }
  1099.             }
  1100.             if (ok) {
  1101.                 // Link all points - link top left to bottom right
  1102.                 for (x = 0;
  1103.                         x <= xgrid;
  1104.                         ++x) {
  1105.                     for (y = 0;
  1106.                             y <= ygrid;
  1107.                             ++y) {
  1108.                         if (x < xgrid) {
  1109.                             LinkPoints(MyPointp[x*(xgrid+1)+y],MyPointp[(x+1)*(xgrid+1)+y]);
  1110.                         }
  1111.                         if (y < ygrid) {
  1112.                             LinkPoints(MyPointp[x*(xgrid+1)+y],MyPointp[x*(xgrid+1)+y+1]);
  1113.                         }
  1114.                     }
  1115.                 }
  1116.             }
  1117.             // Free the Points pointers
  1118.             FreeMem(MyPointp,sizeof(struct MyPoint *)*((xgrid+1)*(ygrid+1)));
  1119.         }
  1120.         else {
  1121.             ok = FALSE;
  1122.         }
  1123.     }
  1124.     else {
  1125.         Error("Both X Cells and Y Cells must be > 0","OK",NULL,HE_Grid0);
  1126.     }
  1127.     if (!ok) {
  1128.         Error("Out of memory for points","OK",NULL,HE_MPoints);
  1129.     }
  1130. }
  1131.  
  1132. /* Display help on a control or image window menu
  1133.  * Code    : menu code
  1134.  * Note: this is a virtual clone of the code above (with 1 changed to M_SETTINGS)
  1135.  */
  1136. void
  1137. DoMenuHelp(USHORT Code) {
  1138.     ULONG HNum;        // Help node
  1139.     /* Reset everything which could have been set
  1140.      * using the menu
  1141.      */
  1142.     RemoveMenus();
  1143.     MySetMode(Mode);
  1144.     // Forget any previous changes
  1145.     SwitchMenuItem(MM_PALETTE,palette,FALSE);
  1146.     SwitchMenuItem(MM_ZOOM,Zoom,FALSE);
  1147.     SwitchMenuItem(MM_ICONSP,CreateIconsP,FALSE);
  1148.     UpdateOpenMode(FALSE);
  1149.     SwitchMenuItem(MM_ICONSR,CreateIconsR,FALSE);
  1150.     UpdateRenderMode(FALSE);
  1151.     UpdateSaveFormat(FALSE);
  1152.     AddMenus();
  1153.     // Determine help node
  1154.     switch (Code) {
  1155.     case FULLMENUNUM(M_PROJECT,NOITEM,NOSUB):
  1156.     case FULLMENUNUM(M_PROJECT,MM_B1,NOSUB):
  1157.     case FULLMENUNUM(M_PROJECT,MM_B2,NOSUB):
  1158.     case FULLMENUNUM(M_PROJECT,MM_B3,NOSUB):
  1159.     case FULLMENUNUM(M_PROJECT,MM_B4,NOSUB):
  1160.     case FULLMENUNUM(M_PROJECT,MM_B5,NOSUB):
  1161.         HNum = H_CMP;
  1162.         break;
  1163.     case FULLMENUNUM(M_PROJECT,MM_NEW,NOSUB):
  1164.         HNum = H_CMPN;
  1165.         break;
  1166.     case FULLMENUNUM(M_PROJECT,MM_OPEN,NOSUB):
  1167.         HNum = H_CMPO;
  1168.         break;
  1169.     case FULLMENUNUM(M_PROJECT,MM_SAVE,NOSUB):
  1170.         HNum = H_CMPS;
  1171.         break;
  1172.     case FULLMENUNUM(M_PROJECT,MM_SAVEAS,NOSUB):
  1173.         HNum = H_CMPSA;
  1174.         break;
  1175.     case FULLMENUNUM(M_PROJECT,MM_ABOUT,NOSUB):
  1176.         HNum = H_CMPA;
  1177.         break;
  1178.     case FULLMENUNUM(M_PROJECT,MM_EXITPOINTS,NOSUB):
  1179.         HNum = H_CMPE;
  1180.         break;
  1181.     case FULLMENUNUM(M_PROJECT,MM_QUIT,NOSUB):
  1182.         HNum = H_CMPQ;
  1183.         break;
  1184.     case FULLMENUNUM(M_PROJECT,MM_PPREVIEW,NOSUB):
  1185.         HNum = H_CMPP;
  1186.         break;
  1187.     case FULLMENUNUM(M_EDIT,NOITEM,NOSUB):
  1188.         HNum = H_CME;
  1189.         break;
  1190.     case FULLMENUNUM(M_EDIT,MM_GRID,NOSUB):
  1191.         HNum = H_CMEG;
  1192.         break;
  1193.     case FULLMENUNUM(M_EDIT,MM_FRAME,NOSUB):
  1194.         HNum = H_CMEF;
  1195.         break;
  1196.     case FULLMENUNUM(M_EDIT,MM_FRAME,MI_FIRST):
  1197.         HNum = H_CMEFF;
  1198.         break;
  1199.     case FULLMENUNUM(M_EDIT,MM_FRAME,MI_PREV):
  1200.         HNum = H_CMEFP;
  1201.         break;
  1202.     case FULLMENUNUM(M_EDIT,MM_FRAME,MI_GOTO):
  1203.         HNum = H_CMEFG;
  1204.         break;
  1205.     case FULLMENUNUM(M_EDIT,MM_FRAME,MI_NEXT):
  1206.         HNum = H_CMEFN;
  1207.         break;
  1208.     case FULLMENUNUM(M_EDIT,MM_FRAME,MI_LAST):
  1209.         HNum = H_CMEFL;
  1210.         break;
  1211.     case FULLMENUNUM(M_EDIT,MM_MODE,NOSUB):
  1212.         HNum = H_CMSM;
  1213.         break;
  1214.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_EDITONE):
  1215.         HNum = H_EOne;
  1216.         break;
  1217.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_EDITTWO):
  1218.         HNum = H_ETwo;
  1219.         break;
  1220.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_EDITREL):
  1221.         HNum = H_ERel;
  1222.         break;
  1223.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_ADD):
  1224.         HNum = H_EAdd;
  1225.         break;
  1226.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_DELETE):
  1227.         HNum = H_EDel;
  1228.         break;
  1229.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_LINK):
  1230.         HNum = H_ELnk;
  1231.         break;
  1232.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_UNLINK):
  1233.         HNum = H_EUnl;
  1234.         break;
  1235.     case FULLMENUNUM(M_EDIT,MM_MODE,MI_NONE):
  1236.         HNum = H_EMov;
  1237.         break;
  1238.     case FULLMENUNUM(M_SETTINGS,NOITEM,NOSUB):
  1239.     case FULLMENUNUM(M_SETTINGS,MM_C1,NOSUB):
  1240.     case FULLMENUNUM(M_SETTINGS,MM_C2,NOSUB):
  1241.     case FULLMENUNUM(M_SETTINGS,MM_C3,NOSUB):
  1242.     case FULLMENUNUM(M_SETTINGS,MM_C4,NOSUB):
  1243.         HNum = H_IMS;
  1244.         break;
  1245.     case FULLMENUNUM(M_SETTINGS,MM_ICONS,NOSUB):
  1246.         HNum = H_P_CI;
  1247.         break;
  1248.     case FULLMENUNUM(M_SETTINGS,MM_PALETTE,NOSUB):
  1249.         HNum = H_P_CP;
  1250.         break;
  1251.     case FULLMENUNUM(M_SETTINGS,MM_ZOOM,NOSUB):
  1252.         HNum = H_P_ZO;
  1253.         break;
  1254.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,NOSUB):
  1255.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,MI_ALWAYS):
  1256.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,MI_IFILBM):
  1257.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,MI_IFCOLOURS):
  1258.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,MI_REMAP):
  1259.     case FULLMENUNUM(M_SETTINGS,MM_OPENMODE,MI_OPAL):
  1260.         HNum = H_P_OM;
  1261.         break;
  1262.     case FULLMENUNUM(M_SETTINGS,MM_SCREEN,NOSUB):
  1263.         HNum = H_P_PS;
  1264.         break;
  1265.     case FULLMENUNUM(M_SETTINGS,MM_CUSTOM,NOSUB):
  1266.         HNum = H_PCUSTM;
  1267.         break;
  1268.     case FULLMENUNUM(M_SETTINGS,MM_CDEPTH,NOSUB):
  1269.         HNum = H_PCUSTD;
  1270.         break;
  1271.     case FULLMENUNUM(M_SETTINGS,MM_SPREVIEW,NOSUB):
  1272.         HNum = H_P_Preview;
  1273.         break;
  1274.     case FULLMENUNUM(M_SETTINGS,MM_ICONSP,NOSUB):
  1275.         HNum = H_P_CIP;
  1276.         break;
  1277.     case FULLMENUNUM(M_SETTINGS,MM_KEEPS,NOSUB):
  1278.         HNum = H_P_KS;
  1279.         break;
  1280.     case FULLMENUNUM(M_SETTINGS,MM_LOADS,NOSUB):
  1281.         HNum = H_P_LOADS;
  1282.         break;
  1283.     case FULLMENUNUM(M_SETTINGS,MM_SAVES,NOSUB):
  1284.         HNum = H_P_SAVES;
  1285.         break;
  1286.     case FULLMENUNUM(M_SETTINGS,MM_SAVESAS,NOSUB):
  1287.         HNum = H_P_SAVESAS;
  1288.         break;
  1289.     case FULLMENUNUM(M_SETTINGS,MM_ICONSR,NOSUB):
  1290.         HNum = H_P_CIR;
  1291.         break;
  1292.     case FULLMENUNUM(M_SETTINGS,MM_DX,NOSUB):
  1293.         HNum = H_P_DX;
  1294.         break;
  1295.     case FULLMENUNUM(M_SETTINGS,MM_DY,NOSUB):
  1296.         HNum = H_P_DY;
  1297.         break;
  1298.     case FULLMENUNUM(M_SETTINGS,MM_LOADSCRIPT,NOSUB):
  1299.         HNum = H_P_LS;
  1300.         break;
  1301.     case FULLMENUNUM(M_SETTINGS,MM_PRESCRIPT,NOSUB):
  1302.         HNum = H_P_PES;
  1303.         break;
  1304.     case FULLMENUNUM(M_SETTINGS,MM_POSTSCRIPT,NOSUB):
  1305.         HNum = H_P_POS;
  1306.         break;
  1307.     case FULLMENUNUM(M_SETTINGS,MM_DEPTH,NOSUB):
  1308.         HNum = H_P_DE;
  1309.         break;
  1310.     case FULLMENUNUM(M_SETTINGS,MM_RENDERMODE,NOSUB):
  1311.     case FULLMENUNUM(M_SETTINGS,MM_RENDERMODE,MI_MODE0):
  1312.     case FULLMENUNUM(M_SETTINGS,MM_RENDERMODE,MI_MODE1):
  1313.     case FULLMENUNUM(M_SETTINGS,MM_RENDERMODE,MI_MODE2):
  1314.     case FULLMENUNUM(M_SETTINGS,MM_RENDERMODE,MI_MODE3):
  1315.         HNum = H_P_MO;
  1316.         break;
  1317.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,NOSUB):
  1318.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_ILBM24):
  1319.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_OPAL24):
  1320.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_OPAL24T):
  1321.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_OPAL24F):
  1322.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_OPAL24FT):
  1323.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_JPEG):
  1324.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_JPEGT):
  1325.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_PBM):
  1326.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_BW16):
  1327.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_BW256):
  1328.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_HAM6):
  1329.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_HAM8):
  1330.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_DCTV3):
  1331.     case FULLMENUNUM(M_SETTINGS,MM_SAVEFORMAT,MI_DCTV4):
  1332.         HNum = H_P_SF;
  1333.         break;
  1334.     case FULLMENUNUM(M_SETTINGS,MM_QUALITY,NOSUB):
  1335.         HNum = H_P_QU;
  1336.         break;
  1337.     case FULLMENUNUM(M_SETTINGS,MM_SCREENR,NOSUB):
  1338.         HNum = H_P_PSR;
  1339.         break;
  1340.     case FULLMENUNUM(M_SETTINGS,MM_ANTIALIAS,NOSUB):
  1341.         HNum = H_P_AA;
  1342.         break;
  1343.     case FULLMENUNUM(M_SETTINGS,MM_RESETD,NOSUB):
  1344.         HNum = H_S_RD;
  1345.         break;
  1346.     case FULLMENUNUM(M_SETTINGS,MM_LASTS,NOSUB):
  1347.         HNum = H_S_LS;
  1348.         break;
  1349.     case FULLMENUNUM(M_SETTINGS,MM_RESTORE,NOSUB):
  1350.         HNum = H_S_R;
  1351.         break;
  1352.     case FULLMENUNUM(M_SETTINGS,MM_HELP,NOSUB):
  1353.         HNum = H_P_HE;
  1354.         break;
  1355.     case MENUNULL:
  1356.     default:
  1357.         HNum = H_CM;
  1358.         break;
  1359.     }
  1360.     help(HNum);
  1361. }
  1362.  
  1363. /* String gadget clicked */
  1364. int
  1365. XCellsClicked(void) {
  1366.     // Display help if required
  1367.     if (GridRequestMsg.Code == 0x5F) {
  1368.         help(H_RAGGX);
  1369.     }
  1370.     return 1;
  1371.  
  1372. }
  1373.  
  1374. /* String gadget clicked */
  1375. int
  1376. YCellsClicked(void) {
  1377.     // Display help if required
  1378.     if (GridRequestMsg.Code == 0x5F) {
  1379.         help(H_RAGGY);
  1380.     }
  1381.     return 1;
  1382. }
  1383.  
  1384. /* OK gadget clicked so add the grid    */
  1385. int
  1386. OKClicked(void) {
  1387.     ReallyAddGrid();
  1388.     return 0;
  1389. }
  1390.  
  1391. /* Cancel clicked  - do not add grid    */
  1392. int
  1393. CancelClicked(void) {
  1394.     return 0;
  1395. }
  1396.  
  1397. /* Close Window - do not add grid    */
  1398. int
  1399. GridRequestCloseWindow(void) {
  1400.     return 0;
  1401. }
  1402.  
  1403. /* Vanilla Key in Add Grid    */
  1404. int
  1405. GridRequestVanillaKey(void) {
  1406.     switch (GridRequestMsg.Code) {
  1407.     case 'o':
  1408.     case 'O':
  1409.         // Same as OK
  1410.         OKClicked();
  1411.         return 0;
  1412.         break;
  1413.     case 'x':
  1414.     case 'X':
  1415.         // Activate string gadget
  1416.         ActivateGadget(GridRequestGadgets[GDX_XCells],GridRequestWnd,NULL);
  1417.         break;
  1418.     case 'y':
  1419.     case 'Y':
  1420.         // Activate string gadget
  1421.         ActivateGadget(GridRequestGadgets[GDX_YCells],GridRequestWnd,NULL);
  1422.         break;
  1423.     case 'c':
  1424.     case 'C':
  1425.         // Cancel
  1426.         return 0;
  1427.         break;
  1428.     }
  1429.     return 1;
  1430. }
  1431.  
  1432. /* Raw key - Only help does anything    */
  1433. int
  1434. GridRequestRawKey(void) {
  1435.     UWORD X,Y;            // Mouse coords
  1436.     ULONG HNum;            // Help node
  1437.     X = GridRequestWnd->MouseX;
  1438.     Y = GridRequestWnd->MouseY;
  1439.     switch (GridRequestMsg.Code) {
  1440.     case 0x5f:
  1441.         // Help key - determine gadget or whole window
  1442.         if (PointInBox(X,Y,GRect[GDX_XCells].MinX,GRect[GDX_XCells].MinY,
  1443.                                 GRect[GDX_XCells].MaxX,GRect[GDX_XCells].MaxY))
  1444.             HNum = H_RAGGX;
  1445.         else
  1446.         if (PointInBox(X,Y,GRect[GDX_YCells].MinX,GRect[GDX_YCells].MinY,
  1447.                                 GRect[GDX_YCells].MaxX,GRect[GDX_YCells].MaxY))
  1448.             HNum = H_RAGGY;
  1449.         else
  1450.         if (PointInBox(X,Y,GRect[GDX_OK].MinX,GRect[GDX_OK].MinY,
  1451.                                 GRect[GDX_OK].MaxX,GRect[GDX_OK].MaxY))
  1452.             HNum = H_RAGGOK;
  1453.         else
  1454.         if (PointInBox(X,Y,GRect[GDX_Cancel].MinX,GRect[GDX_Cancel].MinY,
  1455.                                 GRect[GDX_Cancel].MaxX,GRect[GDX_Cancel].MaxY))
  1456.             HNum = H_RAGGCA;
  1457.         else
  1458.         // should really use dynamic gadget size stuff
  1459.         if (PointInBox(X,Y,0,0,
  1460.                                 20,GridRequestWnd->BorderTop))
  1461.             HNum = H_RAGGCL;
  1462.         else
  1463.         if (PointInBox(X,Y,(GridRequestWnd->Width - 24),0,
  1464.                                 GridRequestWnd->Width,GridRequestWnd->BorderTop))
  1465.             HNum = H_RAGGDE;
  1466.         else
  1467.             HNum = H_RAG;
  1468.         help(HNum);
  1469.         break;
  1470.     }
  1471.     return 1;
  1472. }
  1473.  
  1474. /* If project not saved then
  1475.  * display requester and then
  1476.  * save if required
  1477.  * Returns:    TRUE keep going
  1478.  */
  1479. BOOL
  1480. SaveRequester(void) {
  1481.     struct EasyStruct EasyStruct = {
  1482.         sizeof(struct EasyStruct),
  1483.         0,
  1484.         NULL,
  1485.         NULL,
  1486.         NULL
  1487.     };
  1488.     UBYTE *title = "TSMorph";
  1489.     UBYTE *body = "Unsaved project\n%s";
  1490.     UBYTE *gadget;
  1491.     struct Window *req;
  1492.     LONG gad=-1;
  1493.     ULONG ret = 2;
  1494.     ULONG signals;
  1495.     struct rtHandlerInfo *rth;
  1496.     struct AmigaGuideMsg *agm;
  1497.     BOOL ret1;
  1498.     char *other = &(savedfilename[0]);
  1499.     // Disable the windows and display the requester - using reqtools if available
  1500.     DisableWindows(DI_Unsaved);
  1501.     if (ReqToolsBase) {
  1502.         // set up gadgets depending on availability of amigaguide
  1503.         if (handle) {
  1504.             gadget = "_Save|_Help|_Abandon|_Cancel";
  1505.         }
  1506.         else {
  1507.             gadget = "_Save|_Abandon|_Cancel";
  1508.         }
  1509.         // Loop until Save,Abandon or Cancel pressed
  1510.         while (((ret == 2) && handle) || (gad == -1)) {
  1511.             ret = CALL_HANDLER;
  1512.             if (rtEZRequestTags(body,gadget,NULL,&other,
  1513.                                         RT_ReqHandler, &rth,
  1514.                                         RT_Window, TSMorphWnd,
  1515.                                         RT_Underscore, '_',
  1516.                                         RTEZ_ReqTitle, title,
  1517.                                         TAG_END) == CALL_HANDLER) {
  1518.                 while (ret == CALL_HANDLER) {
  1519.                     if (!rth->DoNotWait) {
  1520.                         signals = Wait(rth->WaitMask | ASig);
  1521.                     }
  1522.                     ret = rtReqHandlerA(rth,signals,NULL);
  1523.                     if ((ret == 2) && handle) {
  1524.                         help(H_Unsaved);
  1525.                     }
  1526.                     if (signals & ASig) {
  1527.                           while (agm = GetAmigaGuideMsg(handle)) {
  1528.                              ReplyAmigaGuideMsg(agm);
  1529.                          }
  1530.                      }
  1531.                 }
  1532.             }
  1533.             else {
  1534.                 ret = 0;
  1535.             }
  1536.             gad = ret;
  1537.         }
  1538.     }
  1539.     else {
  1540.         EasyStruct.es_TextFormat = body;
  1541.         EasyStruct.es_Title = title;
  1542.         // set up gadgets depending on availability of amigaguide
  1543.         if (handle) {
  1544.             EasyStruct.es_GadgetFormat = "Save|Help|Abandon|Cancel";
  1545.         }
  1546.         else {
  1547.             EasyStruct.es_GadgetFormat = "Save|Abandon|Cancel";
  1548.         }
  1549.         req = BuildEasyRequest(TSMorphWnd,&EasyStruct,NULL,savedfilename);
  1550.         // Loop until Save,Abandon or Cancel pressed
  1551.         while ((((gad = SysReqHandler(req,NULL,TRUE)) == 2) && handle) ||
  1552.                  (gad == -1)) {
  1553.             if (handle) {
  1554.                 help(H_Unsaved);
  1555.             }
  1556.         }
  1557.         FreeSysRequest(req);
  1558.     }
  1559.     switch(gad) {
  1560.     case 1:
  1561.         if (*savedfilename) {
  1562.             ret1 = SaveAs(savedfilename);
  1563.         }
  1564.         else {
  1565.             ret1 = SaveAs(NULL);
  1566.         }
  1567.         break;
  1568.     case 2:
  1569.     case 3:                // 2 if no help, 3 otherwise
  1570.         ret1 = TRUE;
  1571.         break;
  1572.     case 0:
  1573.         ret1 = FALSE;
  1574.         break;
  1575.     }
  1576.     EnableWindows();
  1577.     return ret1;
  1578. }
  1579.  
  1580. /* Link two points
  1581.  * Drawing in the windows if open
  1582.  */
  1583. void
  1584. LinkPoints(struct MyPoint* MyPoint,struct MyPoint *MyPoint1) {
  1585.     // Link in first free position
  1586.     if (!MyPoint->p1) {
  1587.         MyPoint->p1 = MyPoint1;
  1588.     }
  1589.     else {
  1590.         if (!MyPoint->p2) {
  1591.             MyPoint->p2 = MyPoint1;
  1592.         }
  1593.         else {
  1594.             if (!MyPoint->p3) {
  1595.                 MyPoint->p3 = MyPoint1;
  1596.             }
  1597.             else {
  1598.                 if (!MyPoint->p4) {
  1599.                     MyPoint->p4 = MyPoint1;
  1600.                 }
  1601.             }
  1602.         }
  1603.     }
  1604.     // Same the other way
  1605.     if (!MyPoint1->p1) {
  1606.         MyPoint1->p1 = MyPoint;
  1607.     }
  1608.     else {
  1609.         if (!MyPoint1->p2) {
  1610.             MyPoint1->p2 = MyPoint;
  1611.         }
  1612.         else {
  1613.             if (!MyPoint1->p3) {
  1614.                 MyPoint1->p3 = MyPoint;
  1615.             }
  1616.             else {
  1617.                 if (!MyPoint1->p4) {
  1618.                     MyPoint1->p4 = MyPoint;
  1619.                 }
  1620.             }
  1621.         }
  1622.     }
  1623.     // If windows open then draw points and lines
  1624.     if (Pic1_Open) {
  1625.         MyDraw(Pic1.Win->RPort,MyPoint1->x<<Zoom,MyPoint1->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  1626.     }
  1627.     if (Pic2_Open) {
  1628.         MyDraw(Pic2.Win->RPort,MyPoint1->x1<<Zoom,MyPoint1->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  1629.     }
  1630. }
  1631.  
  1632. /* Unlink two points
  1633.  * Drawing on the screen if required
  1634.  */
  1635. void
  1636. UnlinkPoints(struct MyPoint* MyPoint,struct MyPoint *MyPoint1,BOOL MYDraw) {
  1637.     // Erase lines if required
  1638.     if (MYDraw) {
  1639.         MyDraw(Pic1.Win->RPort,MyPoint1->x<<Zoom,MyPoint1->y<<Zoom,MyPoint->x<<Zoom,MyPoint->y<<Zoom);
  1640.         MyDraw(Pic2.Win->RPort,MyPoint1->x1<<Zoom,MyPoint1->y1<<Zoom,MyPoint->x1<<Zoom,MyPoint->y1<<Zoom);
  1641.     }
  1642.     // Unlink each way
  1643.     if (MyPoint->p1 == MyPoint1) {
  1644.         MyPoint->p1 = NULL;
  1645.     }
  1646.     if (MyPoint->p2 == MyPoint1) {
  1647.         MyPoint->p2 = NULL;
  1648.     }
  1649.     if (MyPoint->p3 == MyPoint1) {
  1650.         MyPoint->p3 = NULL;
  1651.     }
  1652.     if (MyPoint->p4 == MyPoint1) {
  1653.         MyPoint->p4 = NULL;
  1654.     }
  1655.     if (MyPoint1->p1 == MyPoint) {
  1656.         MyPoint1->p1 = NULL;
  1657.     }
  1658.     if (MyPoint1->p2 == MyPoint) {
  1659.         MyPoint1->p2 = NULL;
  1660.     }
  1661.     if (MyPoint1->p3 == MyPoint) {
  1662.         MyPoint1->p3 = NULL;
  1663.     }
  1664.     if (MyPoint1->p4 == MyPoint) {
  1665.         MyPoint1->p4 = NULL;
  1666.     }
  1667. }
  1668.  
  1669. /* Find a point in an image given
  1670.  * x and y coordinates
  1671.  * Returns    : NULL if none closeby
  1672.  */
  1673. struct MyPoint *
  1674. FindPoint(struct Picture *pic,WORD x,WORD y) {
  1675.     struct MyPoint *MyPoint;            // Point to look at
  1676.     LONG diff = 36;                        // Must be closer than sqrt(36) pixels
  1677.     LONG diff1;                                // sqr(distance apart) for current point
  1678.     struct MyPoint *RetPoint = NULL;    // Point being returned
  1679.     // adjust coords for zoom and scroll
  1680.     x+=(pic->Left>>Zoom);
  1681.     y+=(pic->Top>>Zoom);
  1682.     // Step thru all points and find closest
  1683.     for (MyPoint = (struct MyPoint *)PointList.lh_Head;
  1684.             MyPoint->MyNode.mln_Succ;
  1685.             MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
  1686.         if (pic == &Pic1) {
  1687.             diff1 = ((MyPoint->x-x)*(MyPoint->x-x)+
  1688.                         (MyPoint->y-y)*(MyPoint->y-y));
  1689.         }
  1690.         else {
  1691.             diff1 = ((MyPoint->x1-x)*(MyPoint->x1-x)+
  1692.                         (MyPoint->y1-y)*(MyPoint->y1-y));
  1693.         }
  1694.           if (diff1<diff) {
  1695.               diff = diff1;
  1696.               RetPoint = MyPoint;
  1697.           }
  1698.     }
  1699.     return RetPoint;
  1700. }
  1701.  
  1702. /* Delete a point
  1703.  * removing all links
  1704.  */
  1705. void
  1706. DeletePoint(struct MyPoint *MyPoint){
  1707.     // Unlink any links
  1708.     if (MyPoint->p1) {
  1709.         UnlinkPoints(MyPoint,MyPoint->p1,FALSE);
  1710.     }
  1711.     if (MyPoint->p2) {
  1712.         UnlinkPoints(MyPoint,MyPoint->p2,FALSE);
  1713.     }
  1714.     if (MyPoint->p3) {
  1715.         UnlinkPoints(MyPoint,MyPoint->p3,FALSE);
  1716.     }
  1717.     if (MyPoint->p4) {
  1718.         UnlinkPoints(MyPoint,MyPoint->p4,FALSE);
  1719.     }
  1720.     // remove from list and free memory
  1721.     Remove((struct Node *)MyPoint);
  1722.     FreeMem(MyPoint,sizeof(struct MyPoint));
  1723. }
  1724.  
  1725. /* Similar to Draw() but always draws top left to bottom right
  1726.  * to prevent stray pixels if erasing by drawing in the other direction
  1727.  */
  1728. void
  1729. MyDraw(struct RastPort *rp, SHORT x, SHORT y, SHORT oldx, SHORT oldy) {
  1730.     if ((oldx < x) || ((oldx == x) && (oldy < y))) {
  1731.         Move(rp,oldx,oldy);
  1732.         Draw(rp,x,y);
  1733.     }
  1734.     else {
  1735.         Move(rp,x,y);
  1736.         Draw(rp,oldx,oldy);
  1737.     }
  1738. }
  1739.  
  1740. /* Shows ASL file requester for a file
  1741.  * name    : current file name
  1742.  * Prompt: Title
  1743.  * flags    : e.g. for save flag
  1744.  * Returns: TRUE if file selected, name is TempFileName
  1745.  */
  1746. BOOL
  1747. GetAFile(char *name,char *Prompt,ULONG flags) {
  1748.     // Split of directory name
  1749.     strncpy(TempFilename,name,PathPart(name) - name);
  1750.     TempFilename[PathPart(name) - name] = 0;
  1751.     // Show requesters
  1752.     if (AslRequestTags((APTR) filereq,
  1753.                             ASL_Hail,(Tag) Prompt,
  1754.                             ASL_FuncFlags,flags,
  1755.                             ASL_Dir, (Tag) TempFilename,
  1756.                             ASL_File,(Tag) FilePart(name),
  1757.                             ASL_Window, TSMorphWnd,
  1758.                             TAG_DONE)) {
  1759.         // rejoin name
  1760.         strncpy(TempFilename,filereq->rf_Dir,256);
  1761.         AddPart(TempFilename,filereq->rf_File,256);
  1762.         return TRUE;
  1763.     }
  1764.     else {
  1765.         return FALSE;
  1766.     }
  1767. }
  1768.  
  1769. /* New selected on the Info window */
  1770. int
  1771. TSMorphMenuNew(void) {
  1772.     // Suggest save if unsaved
  1773.     if (!Saved) {
  1774.         if (!SaveRequester()) {
  1775.             return 1;
  1776.         }
  1777.         DisableWindows(DI_New);
  1778.     }
  1779.     // Reset everything
  1780.     Saved = TRUE;
  1781.     savedfilename[0]=0;
  1782.     DeleteAllPoints();
  1783.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL,
  1784.                             GTST_String, "", TAG_END );
  1785.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL,
  1786.                             GTST_String, "", TAG_END );
  1787.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL,
  1788.                             GTST_String, "", TAG_END );
  1789.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL,
  1790.                             GTST_String, "", TAG_END );
  1791.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL,
  1792.                             GTST_String, "", TAG_END );
  1793.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_Frames],TSMorphWnd,NULL,
  1794.                             GTIN_Number,1, TAG_END );
  1795.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_Start],TSMorphWnd,NULL,
  1796.                             GTIN_Number,0, TAG_END );
  1797.     SinglePicture = 0;
  1798.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_SinglePicture],TSMorphWnd,NULL,
  1799.                             GTCY_Active,SinglePicture, TAG_END );
  1800.     Width = 0;
  1801.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_Width],TSMorphWnd,NULL,
  1802.                             GTNM_Number,Width, TAG_END );
  1803.     Height = 0;
  1804.     GT_SetGadgetAttrs(TSMorphGadgets[GDX_Height],TSMorphWnd,NULL,
  1805.                             GTNM_Number,Height, TAG_END );
  1806.     MaxWidth = 0;
  1807.     MaxHeight = 0;
  1808.     EnableWindows();
  1809.     return 1;
  1810. }
  1811.  
  1812. /* Limit the coordinates of a point to the image size */
  1813. void
  1814. LimitPoints(SHORT *x,SHORT *y,struct Picture *pic) {
  1815.     if (*x < 0)
  1816.         *x = 0;
  1817.     if (*x > pic->ilbm->Bmhd.w-1)
  1818.         *x = pic->ilbm->Bmhd.w-1;
  1819.     if (*y < 0)
  1820.         *y = 0;
  1821.     if (*y > pic->ilbm->Bmhd.h-1)
  1822.         *y = pic->ilbm->Bmhd.h-1;
  1823. }
  1824.  
  1825. static BOOL realfirstcall = TRUE;    // Is this really the first call
  1826.                                                 // not sure I understand this!
  1827.                                                 // but some parameters (e.g. Public screen) must
  1828.                                                 // only be set on the very first call
  1829. // Initialise all settings values from parameters etc.
  1830. void
  1831. InitParams(BOOL firstcall) {
  1832.     UBYTE *omode;
  1833.     ULONG OZoom = Zoom;
  1834.     UBYTE *FormatStr;
  1835.     if (realfirstcall) {
  1836.         PubScreenName     = MyArgString("PUBSCREEN",NULL,!firstcall);
  1837.     }
  1838.     if (realfirstcall || !ControlWindow) {
  1839.         PaletteAllowed = !MatchToolValue(MyArgString("CHANGEPALETTE",PaletteAllowed?"YES":"OFF",!firstcall),"OFF");
  1840.         ZoomAllowed     = !MatchToolValue(MyArgString("ZOOM",ZoomAllowed?"NO":"OFF",!firstcall),"OFF");
  1841.     }
  1842.     realfirstcall = FALSE;
  1843.     strcpy(ScreenName,MyArgString("PUBSCREEN",ScreenName,!firstcall));
  1844.     strcpy(CustomName,MyArgString("CUSTOMMODE",CustomName,!firstcall));
  1845.     CustomDepth = MyArgInt("CUSTOMDEPTH",CustomDepth,!firstcall);
  1846.     strcpy(ScreenNameR,MyArgString("PUBSCREENR",ScreenNameR,!firstcall));
  1847.     CreateIcons     = MatchToolValue(MyArgString("CREATEICONS",CreateIcons?"YES":"NO",!firstcall),"YES");
  1848.     CreateIconsR     = MatchToolValue(MyArgString("CREATEICONSR",CreateIconsR?"YES":"NO",!firstcall),"YES");
  1849.     CreateIconsP     = MatchToolValue(MyArgString("CREATEICONSP",CreateIconsP?"YES":"NO",!firstcall),"YES");
  1850.     KeepSettings   = MatchToolValue(MyArgString("KEEPSETTINGS",KeepSettings?"YES":"NO",!firstcall),"YES");
  1851.     if (PaletteAllowed) {
  1852.         palette             = MatchToolValue(MyArgString("CHANGEPALETTE",palette?"YES":"NO",!firstcall),"YES");
  1853.     }
  1854.     else {
  1855.         palette = FALSE;
  1856.     }
  1857.     if (ZoomAllowed) {
  1858.         Zoom = (MatchToolValue(MyArgString("ZOOM",Zoom?"YES":"NO",!firstcall),"YES") ? 1 : 0);    // Note: not a BOOL
  1859.     }
  1860.     else {
  1861.         Zoom = FALSE;
  1862.     }
  1863.     switch (OpenMode) {
  1864.     case OPEN_ILBM_IF_ILBM:
  1865.         omode = "IFILBM";
  1866.         break;
  1867.     case OPEN_ILBM_ALWAYS:
  1868.         omode = "ALWAYS";
  1869.         break;
  1870.     case OPEN_REMAP:
  1871.         omode = "REMAP";
  1872.         break;
  1873.     case OPEN_OPAL:
  1874.         omode = "OPAL";
  1875.         break;
  1876.     default:
  1877.         omode = "IFCOLOURS";
  1878.         break;
  1879.     }
  1880.     omode = MyArgString("OPENMODE",omode,!firstcall);
  1881.     if (MatchToolValue(omode,"IFILBM")) {
  1882.         OpenMode = OPEN_ILBM_IF_ILBM;
  1883.     }
  1884.     else {
  1885.         if (MatchToolValue(omode,"ALWAYS")) {
  1886.             OpenMode = OPEN_ILBM_ALWAYS;
  1887.         }
  1888.         else {
  1889.             if (MatchToolValue(omode,"REMAP")) {
  1890.                 OpenMode = OPEN_REMAP;
  1891.             }
  1892.             else {
  1893.                 if (MatchToolValue(omode,"OPAL")) {
  1894.                     OpenMode = OPEN_OPAL;
  1895.                 }
  1896.                 else {
  1897.                     OpenMode = OPEN_ILBM_IF_COLOURS;
  1898.                 }
  1899.             }
  1900.         }
  1901.     }
  1902.     switch (SaveFormat) {
  1903.     case MI_OPAL24:
  1904.         FormatStr = "OPAL24";
  1905.         break;
  1906.     case MI_OPAL24T:
  1907.         FormatStr = "OPAL24T";
  1908.         break;
  1909.     case MI_OPAL24F:
  1910.         FormatStr = "OPAL24F";
  1911.         break;
  1912.     case MI_OPAL24FT:
  1913.         FormatStr = "OPAL24FT";
  1914.         break;
  1915.     case MI_JPEG:
  1916.         FormatStr = "JPEG";
  1917.         break;
  1918.     case MI_JPEGT:
  1919.         FormatStr = "JPEGT";
  1920.         break;
  1921.     case MI_PBM:
  1922.         FormatStr = "PPM";
  1923.         break;
  1924.     case MI_BW16:
  1925.         FormatStr = "BW16";
  1926.         break;
  1927.     case MI_BW256:
  1928.         FormatStr = "BW256";
  1929.         break;
  1930.     case MI_HAM6:
  1931.         FormatStr = "HAM6";
  1932.         break;
  1933.     case MI_HAM8:
  1934.         FormatStr = "HAM8";
  1935.         break;
  1936.     case MI_DCTV3:
  1937.         FormatStr = "DCTV3";
  1938.         break;
  1939.     case MI_DCTV4:
  1940.         FormatStr = "DCTV4";
  1941.         break;
  1942.     default:
  1943.         FormatStr = "ILBM24";
  1944.         break;
  1945.     }
  1946.     FormatStr = MyArgString("SAVEFORMAT",FormatStr,!firstcall);
  1947.     if (MatchToolValue(FormatStr,"OPAL24")) {
  1948.         SaveFormat = MI_OPAL24;
  1949.     }
  1950.     else {
  1951.         if (MatchToolValue(FormatStr,"OPAL24T")) {
  1952.             SaveFormat = MI_OPAL24T;
  1953.         }
  1954.         else {
  1955.             if (MatchToolValue(FormatStr,"OPAL24F")) {
  1956.                 SaveFormat = MI_OPAL24F;
  1957.             }
  1958.             else {
  1959.                 if (MatchToolValue(FormatStr,"OPAL24FT")) {
  1960.                     SaveFormat = MI_OPAL24FT;
  1961.                 }
  1962.                 else {
  1963.                     if (MatchToolValue(FormatStr,"JPEG")) {
  1964.                         SaveFormat = MI_JPEG;
  1965.                     }
  1966.                     else {
  1967.                         if (MatchToolValue(FormatStr,"JPEGT")) {
  1968.                             SaveFormat = MI_JPEGT;
  1969.                         }
  1970.                         else {
  1971.                             if (MatchToolValue(FormatStr,"PPM")) {
  1972.                                 SaveFormat = MI_PBM;
  1973.                             }
  1974.                             else {
  1975.                                 if (MatchToolValue(FormatStr,"BW16")) {
  1976.                                     SaveFormat = MI_BW16;
  1977.                                 }
  1978.                                 else {
  1979.                                     if (MatchToolValue(FormatStr,"BW256")) {
  1980.                                         SaveFormat = MI_BW256;
  1981.                                     }
  1982.                                     else {
  1983.                                         if (MatchToolValue(FormatStr,"HAM6")) {
  1984.                                             SaveFormat = MI_HAM6;
  1985.                                         }
  1986.                                         else {
  1987.                                             if (MatchToolValue(FormatStr,"HAM8")) {
  1988.                                                 SaveFormat = MI_HAM8;
  1989.                                             }
  1990.                                             else {
  1991.                                                 if (MatchToolValue(FormatStr,"DCTV3")) {
  1992.                                                     SaveFormat = MI_DCTV3;
  1993.                                                 }
  1994.                                                 else {
  1995.                                                     if (MatchToolValue(FormatStr,"DCTV4")) {
  1996.                                                         SaveFormat = MI_DCTV4;
  1997.                                                     }
  1998.                                                     else {
  1999.                                                         SaveFormat = MI_ILBM24;
  2000.                                                     }
  2001.                                                 }
  2002.                                             }
  2003.                                         }
  2004.                                     }
  2005.                                 }
  2006.                             }
  2007.                         }
  2008.                     }
  2009.                 }
  2010.             }
  2011.         }
  2012.     }
  2013.     Quality = MyArgInt("QUALITY",Quality,!firstcall);
  2014.     strcpy(PreScript,MyArgString("PRESCRIPT",PreScript,!firstcall));
  2015.     strcpy(PostScript,MyArgString("POSTSCRIPT",PostScript,!firstcall));
  2016.     strcpy(LoadScript,MyArgString("LOADSCRIPT",LoadScript,!firstcall));
  2017.     strcpy(PreviewScript,MyArgString("PREVIEW",PreviewScript,!firstcall));
  2018.     DX = MyArgInt("DX",DX,!firstcall);
  2019.     DY = MyArgInt("DY",DY,!firstcall);
  2020.     Depth = MyArgInt("DEPTH",Depth,!firstcall);
  2021.     RenderMode = MyArgInt("MODE",RenderMode,!firstcall);
  2022.     AntiAlias =    MatchToolValue(MyArgString("ANTIALIAS",AntiAlias?"YES":"NO",!firstcall),"YES");
  2023.     GHelp = MatchToolValue(MyArgString("HELP",GHelp?"YES":"NO",!firstcall),"YES");
  2024.     // Update with the new parameters
  2025.     UpdateParams(OZoom);
  2026. }
  2027.  
  2028. // Update to new settings - OZoom is old zoom mode
  2029. void
  2030. UpdateParams(ULONG OZoom) {
  2031.     // remove all the menus
  2032.     RemoveMenus();
  2033.     // change all the menu items
  2034.     SwitchMenuItem(MM_PALETTE,palette,FALSE);
  2035.     if (ZoomAllowed && (Zoom != OZoom)) {
  2036.         // If windows are open and changing zoom then update the zoom
  2037.         if (ControlWindow) {
  2038.             DisableWindows(DI_Zoom);
  2039.             if (OZoom) {
  2040.                 UnZoom();
  2041.             }
  2042.             else {
  2043.                 ReZoom();
  2044.             }
  2045.             EnableWindows();
  2046.         }
  2047.         SwitchMenuItem(MM_ZOOM,Zoom,FALSE);
  2048.     }
  2049.     UpdateOpenMode(FALSE);
  2050.     SwitchMenuItem(MM_ICONSR,CreateIconsR,FALSE);
  2051.     SwitchMenuItem(MM_ICONSP,CreateIconsP,FALSE);
  2052.     SwitchMenuItem(MM_KEEPS,KeepSettings,FALSE);
  2053.     SwitchMenuItem(MM_ANTIALIAS,AntiAlias,FALSE);
  2054.     SwitchMenuItem(MM_HELP,GHelp,FALSE);
  2055.     UpdateRenderMode(FALSE);
  2056.     UpdateSaveFormat(FALSE);
  2057.     // Add the menus back
  2058.     AddMenus();
  2059.     // and disable/enable items
  2060.     if (PaletteAllowed) {
  2061.         if (TSMorphWnd) {
  2062.             OnMenu(TSMorphWnd,FULLMENUNUM(1,MM_PALETTE,NOSUB));
  2063.         }
  2064.         if (ControlWindow) {
  2065.             OnMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,MM_PALETTE,NOSUB));
  2066.         }
  2067.     }
  2068.     else {
  2069.         if (TSMorphWnd) {
  2070.             OffMenu(TSMorphWnd,FULLMENUNUM(1,MM_PALETTE,NOSUB));
  2071.         }
  2072.         if (ControlWindow) {
  2073.             OffMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,MM_PALETTE,NOSUB));
  2074.         }
  2075.     }
  2076.     if (ZoomAllowed) {
  2077.         if (TSMorphWnd) {
  2078.             OnMenu(TSMorphWnd,FULLMENUNUM(1,MM_ZOOM,NOSUB));
  2079.         }
  2080.         if (ControlWindow) {
  2081.             OnMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,MM_ZOOM,NOSUB));
  2082.         }
  2083.     }
  2084.     else {
  2085.         if (TSMorphWnd) {
  2086.             OffMenu(TSMorphWnd,FULLMENUNUM(1,MM_ZOOM,NOSUB));
  2087.         }
  2088.         if (ControlWindow) {
  2089.             OffMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,MM_ZOOM,NOSUB));
  2090.         }
  2091.     }
  2092. }
  2093.  
  2094. /* Preview render
  2095.  * Basically calls ARexx script with parameters - frame number and filename
  2096.  */
  2097. int
  2098. Preview(void) {
  2099.     UBYTE buffer[140];
  2100.     UBYTE buffer1[256];
  2101.     // save first if not saved
  2102.     if (!Saved) {
  2103.         if (!SaveRequester()) {
  2104.             return 1;
  2105.         }
  2106.     }
  2107.     if (GetFrameNumber()) {    // Get the frame number
  2108.         SaveSettings("T:TSMorph.prefs");    // save temporary settings
  2109.         DisableWindows(DI_Preview);        // disable all windows
  2110.         strcpy(buffer,PreviewScript);        // call ARexx script
  2111.         strcat(buffer," %ld %s");
  2112.         sprintf(buffer1,buffer,FrameNumber,savedfilename);
  2113.         SendRxMsg(buffer1,FALSE);
  2114.         EnableWindows();                        // and re-enable windows
  2115.         return 1;
  2116.     }
  2117.     return 1;
  2118. }
  2119.  
  2120. /* Tries to execute a Rexx script
  2121.  * msgtxt = name of script
  2122.  * IgnoreError = TRUE then do not display error message
  2123.  * Returns:    error message
  2124.  */
  2125. LONG
  2126. SendRxMsg(char *msgtxt,BOOL IgnoreError) {
  2127.     struct MsgPort *reply_port;
  2128.     struct MsgPort *rx_port;
  2129.     struct RexxMsg *rx_msg;
  2130.     LONG                 ret             = RC_FATAL;
  2131.  
  2132.     if (reply_port = CreateMsgPort()) {
  2133.        if (rx_msg = CreateRexxMsg(reply_port,"TSM","REXX")) {
  2134.           rx_msg->rm_Args[0] = msgtxt;
  2135.             if (FillRexxMsg(rx_msg,1,0)) {
  2136.                 rx_msg->rm_Action = RXCOMM;
  2137.                 Forbid();
  2138.                 if (rx_port = (struct MsgPort *)FindPort("REXX")) {
  2139.                   PutMsg(rx_port, (struct Message *)rx_msg);
  2140.                   Permit();
  2141.                   WaitPort(reply_port);
  2142.                   ReplyMsg(GetMsg(reply_port));
  2143.                   ret = rx_msg->rm_Result1;
  2144.                  }
  2145.                 else {
  2146.                   Permit();
  2147.                 }
  2148.                 ClearRexxMsg(rx_msg, 1);
  2149.           }
  2150.              DeleteRexxMsg(rx_msg);
  2151.         }
  2152.         DeleteMsgPort(reply_port);
  2153.       }
  2154.     // Display an error message (if required)
  2155.       if (!IgnoreError && ret) {
  2156.           Error("Error sending ARexx message\n'%s'","OK",msgtxt,H_Arexx);
  2157.       }
  2158.       return ret;
  2159. }
  2160.  
  2161. struct Screen *myscreen = NULL;
  2162.  
  2163. /* Opens a custom screen
  2164.  * Public Screen name is ScreenName
  2165.  * Mode name is CustomName
  2166.  * Depth is CustomDepth
  2167.  * Most other stuff is cloned from the WorkBench
  2168.  *
  2169.  * This whole thing needs redoing a bit
  2170.  */
  2171. BOOL
  2172. OpenCustomScreen(void) {
  2173.     struct Screen *Screen;
  2174.     struct NameInfo buff;
  2175.     ULONG id = INVALID_ID;
  2176.     ULONG myid = INVALID_ID;
  2177.     BOOL used[256] = {0,0,0,0,0,0,0,0,    // table of in use palette entry
  2178.                             0,0,0,0,0,0,0,0,    // we use the rest for grey scale
  2179.                             0,0,0,0,0,0,0,0,
  2180.                             0,0,0,0,0,0,0,0,
  2181.                             0,0,0,0,0,0,0,0,
  2182.                             0,0,0,0,0,0,0,0,
  2183.                             0,0,0,0,0,0,0,0,
  2184.                             0,0,0,0,0,0,0,0,
  2185.                             };
  2186.     UWORD numcols;
  2187.     UWORD i;
  2188.     UWORD diff;
  2189.     UBYTE Color;
  2190.     UWORD rgb;
  2191.     BOOL usedri = TRUE;
  2192.     UWORD mydir = ~0;
  2193.     struct DrawInfo *dri = NULL;
  2194.     struct DrawInfo *mydri = NULL;
  2195.     BOOL retflag = TRUE;
  2196.     char *emsg;
  2197.     char *e1=NULL;
  2198.     ULONG err=0;
  2199.  
  2200.     // check we have a name and a mode and depth
  2201.     if (ScreenName && *ScreenName && CustomName && *CustomName && (CustomDepth > 0)) {
  2202.         // check public screen not already open
  2203.         if (!(Screen = LockPubScreen(ScreenName))) {
  2204.             // try and find modeid
  2205.             id = NextDisplayInfo(id);
  2206.             while ((id != INVALID_ID) && (myid == INVALID_ID)) {
  2207.                 if (GetDisplayInfoData(NULL,(UBYTE *)&buff,sizeof(struct NameInfo),DTAG_NAME,id)) {
  2208.                     if (!Stricmp(buff.Name,CustomName)) {
  2209.                         myid = id;
  2210.                     }
  2211.                 }
  2212.                 id = NextDisplayInfo(id);
  2213.             }
  2214.             if (myid != INVALID_ID) {
  2215.                 // Get info from the workbench
  2216.                 if (Screen = LockPubScreen("Workbench")) {
  2217.                     if (dri = GetScreenDrawInfo(Screen)) {
  2218.                         for (i = 0;
  2219.                               i < dri->dri_NumPens;
  2220.                               ++i) {
  2221.                             if (!(dri->dri_Pens[i] < (1<<CustomDepth))) {
  2222.                                 usedri = FALSE;
  2223.                             }
  2224.                         }
  2225.                         // open sort of cloned screen
  2226.                         if (myscreen = OpenScreenTags(NULL,
  2227.                                     SA_Depth, CustomDepth,
  2228.                                     SA_Overscan, OSCAN_TEXT,
  2229.                                     SA_Pens, usedri?((ULONG) (dri->dri_Pens)):((ULONG) &mydir),
  2230.                                     SA_SysFont, 1,
  2231.                                     SA_DisplayID, myid,
  2232.                                     SA_Type, PUBLICSCREEN,
  2233.                                     SA_PubName, ScreenName,
  2234.                                     SA_Title, ScreenName,
  2235.                                     SA_FullPalette, TRUE,
  2236.                                     TAG_END)) {
  2237.                             // set unused palette entries to grey scale
  2238.                             if (mydri = GetScreenDrawInfo(myscreen)) {
  2239.                                 numcols = 1<<CustomDepth;
  2240.                                 for (i = 0;
  2241.                                       i < mydri->dri_NumPens;
  2242.                                       ++i) {
  2243.                                     if (!used[min(mydri->dri_Pens[i],256)]) {
  2244.                                         used[min(mydri->dri_Pens[i],256)] = TRUE;
  2245.                                         --numcols;
  2246.                                     }
  2247.                                 }
  2248.                                 if (numcols) {
  2249.                                     diff = (16 / (numcols + 1));
  2250.                                     Color = diff;
  2251.                                     if (!diff) {
  2252.                                         diff = 1;
  2253.                                     }
  2254.                                     for (i = 0;
  2255.                                           (i < (1<<CustomDepth));
  2256.                                           ++i) {
  2257.                                         if (!used[i] && (Color<16)) {
  2258.                                             SetRGB4(&(myscreen->ViewPort),i,Color,Color,Color);
  2259.                                             Color += diff;
  2260.                                         }
  2261.                                         else {
  2262.                                             if (i < (1<< dri->dri_Depth)) {
  2263.                                                 rgb = GetRGB4(Screen->ViewPort.ColorMap,i);
  2264.                                                 SetRGB4(&(myscreen->ViewPort),i,rgb>>8,(rgb & 0x0f0)>>4,rgb & 0x0f);
  2265.                                             }
  2266.                                         }
  2267.                                     }
  2268.                                 }
  2269.                                 // Free everything, set screen to public and return
  2270.                                 FreeScreenDrawInfo(myscreen,mydri);
  2271.                             }
  2272.                             PubScreenStatus(myscreen,NULL);
  2273.                             FreeScreenDrawInfo(Screen,dri);
  2274.                             UnlockPubScreen(NULL,Screen);
  2275.                             OpenedScreen = TRUE;
  2276.                             return TRUE;
  2277.                         }
  2278.                         // Free everything and display error
  2279.                         else {
  2280.                             retflag = FALSE;
  2281.                             emsg = "Error opening screen";
  2282.                             err = HE_OScreen;
  2283.                         }
  2284.                         FreeScreenDrawInfo(Screen,dri);
  2285.                     }
  2286.                     else {
  2287.                         retflag = FALSE;
  2288.                         emsg = "Unable to get DrawInfo";
  2289.                         err = HE_DrawI;
  2290.                     }
  2291.                     UnlockPubScreen(NULL,Screen);
  2292.                 }
  2293.                 else {
  2294.                     retflag = FALSE;
  2295.                     emsg = "Unable to lock Workbench";
  2296.                     err = HE_LockW;
  2297.                 }
  2298.             }
  2299.             else {
  2300.                 retflag = FALSE;
  2301.                 emsg = "Invalid screen mode %s";
  2302.                 e1 = CustomName;
  2303.                 err = HE_ScreenMode;
  2304.             }
  2305.         }
  2306.         else {
  2307.             UnlockPubScreen(NULL,Screen);
  2308.         }
  2309.     }
  2310.     if (!retflag) {
  2311.         Error(emsg,"Quit",e1,err);
  2312.     }
  2313.     return retflag;
  2314. }
  2315.  
  2316. /* Attempt to close the public screen
  2317.  *
  2318.  * This really is a horrible hack
  2319.  * we just loop for a while (not busy waiting)
  2320.  * and then give up. This may leave the screen open
  2321.  * with a title pointing to unallocated memory.
  2322.  *
  2323.  * This should be based on the Signal when last window is shut!
  2324.  */
  2325. void
  2326. CloseCustomScreen(void) {
  2327.     int i;
  2328.     for (i=0; i < 20; ++i) {
  2329.         if (CloseScreen(myscreen)) {
  2330.             break;
  2331.         }
  2332.         Delay(50);
  2333.     }
  2334. }
  2335.